<?php
/**
 * Created by PhpStorm.
 * User: lili
 * Date: 2018/12/30
 * Time: 23:44
 */

namespace system\core\view;


use system\core\config\Config;
use system\core\route\Request;

class View
{


    protected $request ;

    protected static $instance;

    //模板存放路径
    public $template = '/resources/view/';
    //编译后模板路径
    public $template_c = '/caches/view_c/';

    //存放变量的数组,通过assign函数赋值
    public $var = array();

    //模板内容
    public $template_content ='';

    public function __construct()
    {
        $this->request = Request::getInstance();
        $viewconf = Config::get('view');
        if (!empty($viewconf)){

            $this->template = substr(ROOT_PATH,0,-1) .$viewconf['template'];
            $this->template_c = substr(ROOT_PATH,0,-1).$viewconf['template_c'];
        }

    }

    /**
     * 初始化
     * @access public
     * @param array $options 参数
     * @return \system\core\view\view
     */
    public static function getInstance()
    {

        if (empty(self::$instance)) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    //变量赋值
    public function assign($vkey,$value){
        if($vkey != ""){
            $this->var[$vkey] = $value;//把要模板中解析的数据压入数组
        }
    }

    //模板中变量替换
    public function display($path){
        $pathmd5 = md5($path);
        $template_path = $this->template.$path.".html";
        $template_c_path = $this->template_c.$pathmd5.".php";

        if(!file_exists($template_path)){
            return false;
        }

        //只有解析后的模板文件不存在或者模板源文件有新的改动的情况下 重新解析模板
        if(!file_exists($template_c_path) || filemtime($template_path)>filemtime($template_c_path)){
            //获取模板源文件，用来替换

            $this->template_content = file_get_contents($template_path);

            $this->compile();

            //编译后文件写入某个目录

            if(!is_dir(dirname($template_c_path))){
                //文件夹缺失，创建文件夹
                mkdir(dirname($template_c_path),0755,true);
            }
            if (!file_exists($template_c_path)){
                //文件缺失，创建缓存文件
                touch($template_c_path);
            }


            file_put_contents($template_c_path,$this->template_content);
        }
        //引入编译后文件，其实就是执行了那个php文件的代码
        include_once $template_c_path;

    }


    /*
     * 变量直接输出标签{$var} $var 普通变量或者数组 {$name['sex']['f']}
     * @param string $template_content [编译前的字符串]
     * @return stirng $res [编译后的字符串]
     * */
    public function parvar($template_content){
        $pattern = array(
            '/\{\s*\$([a-zA-Z][a-zA-Z0-9_]*)([a-zA-Z0-9_\'\"\[\]]*)\s*\}/i',
        );
        $replace = array(
            '<?php echo $this->var["${1}"]${2}; ?>',
        );

        if (preg_match($pattern[0],$template_content )){
            //用正则去替换模板源文件中的变量符号{$varname}
            $template_content = preg_replace($pattern,$replace,$template_content);
        }


        return $template_content;
    }





    /*
     *
     * 解析if标签
     *
     *
     * */
    public function parif($template_content){
        $pattern_ifs = '/\{if\s\((.*)\)\s*\}/i';//开始标签

        $pattern_ife = '/\{\/if\s*\}/i';//结束标签

        $pattern_else = '/\{\/else\s*\}/i';//else标签


        $replace_s = '<?php if( ${1} ) { ?>';

        $replace_e = '<?php } ?>';

        $replace_else = '<?php }else{ ?>';
        
        //标签的替代
        if (preg_match($pattern_ifs, $template_content,$matches)){
            if (preg_match($pattern_ife, $template_content)){
                $template_content = preg_replace($pattern_ifs,$replace_s,$template_content);
                $template_content = preg_replace($pattern_ife,$replace_e,$template_content);

                //括号里面的替代
                $pattern_in = '/\$([a-zA-Z][a-zA-Z0-9_]*)([a-zA-Z0-9_\'\"\[\]]*)/i';
                $replace_in = '!empty(\$this->var["${1}"]${2})?\$this->var["${1}"]${2}:\$$1$2';
                if (preg_match($pattern_in, $matches[1])){
                    $instr = preg_replace($pattern_in,$replace_in ,$matches[1]);
                    $template_content = str_replace($matches[1], $instr, $template_content);
                }

                if (preg_match($pattern_else,$template_content )){
                    $template_content = preg_replace($pattern_else,$replace_else,$template_content);
                }
            }else{
                throw new \Exception("if结束符缺失");
            }
        }
        return $template_content;
    }
    

    
    /*
     * 编译foreach，数组遍历
     *
     *
     * */
    public function parforeach($template_content){
        //开始
        $pattern_f = '/\{foreach\s+name=\"(([a-zA-Z][a-zA-Z0-9_]*)([a-zA-Z0-9_\'\"\[\]]*))\"\s+key=\"([a-zA-Z][a-zA-Z0-9_]*)\"\s+value=\"([a-zA-Z][a-zA-Z0-9_]*)\"\s*\}/';
//        $patternForeach = '/\{foreach\s+name=\"(\$([a-zA-Z][a-zA-Z0-9_]*)([a-zA-Z0-9_\'\"\[\]]*))\"\s+key=\"(.*)\"\s+value=\"(.*)\"\s*\}/';

        //结束
        $pattern_e = '/\{\/foreach\}/';

        //foreach里的值
        $pattern_in = '/\{@([a-zA-Z][a-zA-Z0-9_]*)\}/';


        //第一层
        $replace_f = "<?php foreach( !empty(\$this->var['$2']$3)?\$this->var['$2']$3:\$$2$3 as \$$4=>\$$5){?>";

       

        $replace_e = "<?php } ?>";

        $replace_in = "<?php echo \$$1  ?>";


        if(preg_match($pattern_f, $template_content,$matches)){
//            var_dump($matches);
            //判断结束标志
            if(preg_match($pattern_e, $template_content)){
                //替换开头
                $template_content = preg_replace($pattern_f, $replace_f, $template_content);
                //替换结束
                $template_content = preg_replace($pattern_e, $replace_e, $template_content);
                //替换值
                $template_content = preg_replace($pattern_in,$replace_in , $template_content);
            }else{
                throw new \Exception('foreach语句没有关闭');
            }
        }
        return $template_content;
    }


    /*
     * 静态资源文件载入
     * 
     * */
    public function parresources($template_content){

        $template_content = str_replace('@resources',$this->request->getRoot().DS.'resources' ,$template_content );
        
        
        return $template_content;
    }



        /*
         * 编译
         *
         * */
    public function compile(){
        $this->template_content = $this->parvar($this->template_content);
        $this->template_content = $this->parif($this->template_content);
        $this->template_content = $this->parforeach($this->template_content);
        $this->template_content = $this->parresources($this->template_content);
    }





}